﻿using System;
using System.Linq;
using System.Web.Security;
using System.Collections.Generic;

namespace FranceTriple.Dal
{
    public class LaBaFFDal
    {
        public List<FriendlyTeam> GetFriendlyTeamList()
        {
            List<FriendlyTeam> query;
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    query = (from t in ctx.FriendlyTeamSet
                                 orderby t.NameFriendlyTeam
                                 select t).ToList();

                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetFriendlyTeamList", ex.Message), ex) { EntityType = typeof(List<FriendlyTeam>) };
            }
            return query;
        }
        public static GameServer[] GetGameServerByTeamByNicknameGame(Int32 TeamId, String NicknameGame)
        {
            GameServer[] gameserver;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    gameserver = (from gs in ctx.GameServerSet.Include("Game").Include("FriendlyTeam")
                                  where gs.FriendlyTeam.Id==TeamId && gs.Game.NicknameGame.ToLower() == NicknameGame.ToLower() 
                                  select gs).ToArray();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetGameServerByTeamByNicknameGame", ex.Message), ex) { EntityType = typeof(GameServer) };
            }
            return gameserver;
        }

        #region Gestion des GuildMasters
        /// <summary>
        /// Tableau des noms des guildmasters d'une team.
        /// </summary>
        /// <param name="TeamId"></param>
        /// <returns></returns>
        public static Guid[] GetTeamGuildMasterGuids(Int32 TeamId)
        {
            Guid[] teamGuildMasters;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    teamGuildMasters = (from team in ctx.FriendlyTeamSet.Include("FriendlyTeamGuildMaster").Where(t => t.Id == TeamId)
                                                from member in team.FriendlyTeamGuildMaster
                                                select member.UserId).ToArray();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetTeamGuildMasterNames", ex.Message), ex) { EntityType = typeof(String[]) };
            }
            return teamGuildMasters;
        }

        /// <summary>
        /// Tableau des noms des guildmasters d'une team.
        /// </summary>
        /// <param name="TeamId"></param>
        /// <returns></returns>
        public static String[] GetTeamGuildMasterNames(Int32 TeamId)
        {
            String[] teamGuildMasters;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var guildmasterMembersId = (from team in ctx.FriendlyTeamSet.Include("FriendlyTeamGuildMaster").Where(t => t.Id == TeamId)
                                                from member in team.FriendlyTeamGuildMaster
                                                select member.UserId).ToList();

                    teamGuildMasters =
                    (from m in new UserProfile().GetUserRoleMembershipArray("FriendlyTeamGuildMaster").Where(u => guildmasterMembersId.Contains(Guid.Parse(u.ProviderUserKey.ToString())))
                     join p in new UserProfile().GetUserRoleProfileArray("FriendlyTeamGuildMaster")
                 on m.UserName equals p.UserName
                     orderby m.UserName
                     select p.Bf3BattlelogProfilLink).ToArray();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetTeamGuildMasterNames", ex.Message), ex) { EntityType = typeof(String[]) };
            }
            return teamGuildMasters;
        }

        /// <summary>
        /// Ajout un guildmaster à une team et lui ajouter le role FriendlyTeamGuildMaster s'il ne l'a pas déjà
        /// </summary>
        /// <param name="TeamId"></param>
        /// <param name="UserId"></param>
        public static void AddGuildMasterToFriendlyTeam(Int32 TeamId, Guid UserId)
        {
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    FriendlyTeamGuildMaster friend = new FriendlyTeamGuildMaster();
                    friend.FriendlyTeam = (FriendlyTeam)ctx.GetObjectByKey((from teamsFriend in ctx.FriendlyTeamSet.Where(t => t.Id == TeamId) select teamsFriend).FirstOrDefault().EntityKey); ;
                    friend.UserId = UserId;
                    ctx.AddToFriendlyTeamGuildMasterSet(friend);
                    ctx.SaveChanges();

                    String userName = Membership.GetUser(UserId).UserName;
                    if (!Roles.IsUserInRole(userName, "FriendlyTeamGuildMaster"))
                        Roles.AddUserToRole(userName, "FriendlyTeamGuildMaster");
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("InsertError".ToLocalizedString(), "AddGuildMasterToFriendlyTeam", ex.Message), ex) { EntityType = typeof(FriendlyTeamGuildMaster) };
            }
        }

        /// <summary>
        /// Retirer un guildmaster d'une team et lui retirer le role FriendlyTeamGuildMaster s'il est guildmaster d'aucune autre team.
        /// </summary>
        /// <param name="TeamId"></param>
        /// <param name="UserId"></param>
        public static void RemoveGuildMasterFromFriendlyTeam(Int32 TeamId, Guid UserId)
        {
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var guildmasterToUpdate = (from guildmaster in ctx.FriendlyTeamGuildMasterSet
                                               where guildmaster.UserId == UserId && guildmaster.TeamId == TeamId
                                               select guildmaster).FirstOrDefault();
                    ;
                    if (guildmasterToUpdate == null)
                        return;

                    ctx.FriendlyTeamGuildMasterSet.DeleteObject(guildmasterToUpdate);
                    ctx.SaveChanges();

                    String userName = Membership.GetUser(UserId).UserName;
                    if ((from guildmaster in ctx.FriendlyTeamGuildMasterSet.Where(g => g.UserId == UserId)
                         select guildmaster.TeamId).Count() == 0)
                        Roles.RemoveUserFromRole(userName, "FriendlyTeamGuildMaster");

                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("DeleteError".ToLocalizedString(), "RemoveGuildMasterFromFriendlyTeam", ex.Message), ex) { EntityType = typeof(FriendlyTeamGuildMaster) };
            }
        }

        /// <summary>
        /// Tableau des GuildMaster Membershipuser d'une team amies
        /// dans le but de sélectionner un GuildMaster à retirer de la team
        /// </summary>
        /// <param name="TeamId"></param>
        /// <returns></returns>
        public static MembershipUser[] GetTeamGuildMasterMembershipUsersArray(Int32 TeamId)
        {
            MembershipUser[] guildMasters;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var guildmastersId = (from team in ctx.FriendlyTeamSet.Include("FriendlyTeamGuildMaster").Where(t => t.Id == TeamId)
                                          from guildmaster in team.FriendlyTeamGuildMaster
                                          select guildmaster.UserId).ToList();

                    guildMasters = (from user in new UserProfile().GetAllMembershipUserArray().Where(u => guildmastersId.Contains(Guid.Parse(u.ProviderUserKey.ToString())))
                                    select user).ToArray();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetTeamGuildMasterMembershipUsersArray", ex.Message), ex) { EntityType = typeof(MembershipUser[]) };
            }
            return guildMasters;
        }

        /// <summary>
        /// Tableau des GuildMaster Membershipusers qui ne sont pas dans le role "member" et qui ne sont pas dans la Team TeamId
        /// dans le but de sélectionner le GuildMaster à ajouter à une team
        /// </summary>
        /// <returns></returns>
        public static MembershipUser[] GetTeamNonGuildMasterMembershipUsersArray(Int32 TeamId)
        {
            var thisGuildMasters = (from mName in GetTeamGuildMasterMembershipUsersArray(TeamId)
                                    select mName.UserName.ToLower()).ToArray();

            var userCol = Membership.GetAllUsers();
            var userColCount = userCol.Count;
            var userTab = new MembershipUser[userColCount];
            var j = 0;
            foreach (MembershipUser user in userCol)
            {
                userTab[j++] = user;
            }

            userTab = (from user in userTab
                       where !thisGuildMasters.Contains(user.UserName.ToLower())
                       select user).ToArray();

            return userTab;
        }

        #endregion

        #region Gestion des Joueurs
        /// <summary>
        /// Tableau des noms des joueurs d'une team
        /// </summary>
        /// <param name="TeamId"></param>
        /// <returns></returns>
        public static String[] GetTeamMemberNames(Int32 TeamId)
        {
            String[] teamMembers;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var membersId = (from team in ctx.FriendlyTeamSet.Include("FriendlyTeamMember").Where(t => t.Id == TeamId)
                                     from member in team.FriendlyTeamMember
                                     select member.UserId).ToList();

                    teamMembers = (from m in new UserProfile().GetUserRoleMembershipArray("FriendlyTeamMember").Where(u => membersId.Contains(Guid.Parse(u.ProviderUserKey.ToString())))
                                   join p in new UserProfile().GetUserRoleProfileArray("FriendlyTeamMember")
                               on m.UserName equals p.UserName
                                   orderby m.UserName
                                   select p.Bf3BattlelogProfilLink).ToArray();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetTeamMembers", ex.Message), ex) { EntityType = typeof(String[]) };
            }
            return teamMembers;
        }

        /// <summary>
        /// Ajouter un joueur à une équipe et ajouter le role FriendlyTeamMember s'il ne l'a pas déjà
        /// </summary>
        /// <param name="TeamId"></param>
        /// <param name="UserId"></param>
        public static void AddMemberToFriendlyTeam(Int32 TeamId, Guid UserId)
        {
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    FriendlyTeamMember friend = new FriendlyTeamMember();
                    friend.FriendlyTeam = (FriendlyTeam)ctx.GetObjectByKey((from teamsFriend in ctx.FriendlyTeamSet.Where(t => t.Id == TeamId) select teamsFriend).FirstOrDefault().EntityKey); ;
                    friend.UserId = UserId;
                    ctx.AddToFriendlyTeamMemberSet(friend);
                    ctx.SaveChanges();

                    String userName = Membership.GetUser(UserId).UserName;
                    if (!Roles.IsUserInRole(userName, "FriendlyTeamMember"))
                        Roles.AddUserToRole(userName, "FriendlyTeamMember");
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("InsertError".ToLocalizedString(), "AddMemberToFriendlyTeam", ex.Message), ex) { EntityType = typeof(FriendlyTeamMember) };
            }
        }

        /// <summary>
        /// Retirer un joueur d'une équipe et retirer le role FriendlyTeamMember s'il est joueur dans aucune team
        /// </summary>
        /// <param name="TeamId"></param>
        /// <param name="UserId"></param>
        public static void RemoveMemberFromFriendlyTeam(Int32 TeamId, Guid UserId)
        {
            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var memberToUpdate = (from member in ctx.FriendlyTeamMemberSet
                                          where member.UserId == UserId && member.TeamId == TeamId
                                          select member).FirstOrDefault();
                    ;
                    if (memberToUpdate == null)
                        return;

                    ctx.FriendlyTeamMemberSet.DeleteObject(memberToUpdate);
                    ctx.SaveChanges();

                    String userName = Membership.GetUser(UserId).UserName;
                    if ((from teammember in ctx.FriendlyTeamMemberSet.Where(m => m.UserId == UserId)
                         select teammember.TeamId).Count() == 0)
                        Roles.RemoveUserFromRole(userName, "FriendlyTeamMember");
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("DeleteError".ToLocalizedString(), "RemoveMemberFromFriendlyTeam", ex.Message), ex) { EntityType = typeof(FriendlyTeamMember) };
            }
        }

        /// <summary>
        /// Tableau des Membership user d'une team amies
        /// dans le but de sélectionner un joueur à retirer de la team
        /// </summary>
        /// <param name="TeamId"></param>
        /// <returns></returns>
        public static MembershipUser[] GetTeamMembershipUsersArray(Int32 TeamId)
        {
            MembershipUser[] teamMembers;

            try
            {
                using (FranceTriple.Dal.Model1Container ctx = new Model1Container())
                {
                    var membersId = (from team in ctx.FriendlyTeamSet.Include("FriendlyTeamMember").Where(t => t.Id == TeamId)
                                     from member in team.FriendlyTeamMember
                                     select member.UserId).ToList();

                    teamMembers = (from user in new UserProfile().GetAllMembershipUserArray().Where(u => membersId.Contains(Guid.Parse(u.ProviderUserKey.ToString())))
                                   select user).ToArray();
                }
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetTeamMembers", ex.Message), ex) { EntityType = typeof(String[]) };
            }
            return teamMembers;
        }

        /// <summary>
        /// Tableau des Membershipusers qui ne sont pas dans le role "member" et qui ne sont pas dans la Team TeamId
        /// dans le but de sélectionner le joueur à ajouter à une team
        /// </summary>
        /// <returns></returns>
        public static MembershipUser[] GetTeamNonMembershipUsersArray(Int32 TeamId)
        {
            var thisTeamMembers = (from mName in GetTeamMembershipUsersArray(TeamId)
                                   select mName.UserName.ToLower()).ToArray();

            var userCol = Membership.GetAllUsers();
            var userColCount = userCol.Count;
            var userTab = new MembershipUser[userColCount];
            var j = 0;
            foreach (MembershipUser user in userCol)
            {
                userTab[j++] = user;
            }

            userTab = (from user in userTab
                       where !thisTeamMembers.Contains(user.UserName.ToLower())
                       select user).ToArray();

            return userTab;
        }
        #endregion
    }
}
